//
//  RequestService+Account.swift
//  TuneMate
//
//  Created by 丸子 on 2023/11/30.
//

import UIKit
import Alamofire
import Swime

extension RequestService {
    
    func getSendCode(_ account: String, loginType:Int, completeClosure: (() -> Void)?) {
        
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "account":account,
                                                               "loginType":"\(loginType)"])
        session.request("\(apiHost)/api/login/sendCode",
                        method: .post,
                        parameters: ["loginType":loginType,
                                     "sign":sign,
                                     "account":account], encoding: JSONEncoding.default) 
        .responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any],
                      let current = jsonDic["code"] as? String, current == "200" else { return }
                completeClosure?()
            case let .failure(error):
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
    func phoneLogin(_ account: String, code:String,loginType:Int, completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "account":account,
                                                               "loginType":"\(loginType)",
                                                               "loginCode":code])
        session.request("\(apiHost)/api/login/toLogin",
                        method: .post,
                        parameters: ["loginType":loginType,
                                     "sign":sign,
                                     "account":account,
                                     "loginCode":code])
        .responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any],
                      let current = jsonDic["code"] as? String, current == "200", let result = jsonDic["result"] as? [String :Any], let model = AccountModel.deserialize(from: result) else { return }
                SqlManager.shared.insert([model])
                Appearance.shared.accoutModel = model
                GlobalRx.loginSuccessSubject.onNext(())
                self.getUserInfo()
//                self.accountData(result: result)
                completeClosure?()
            case let .failure(error):
                failureClosure?(error.errorDescription)
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
    func deviceLogin(completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "deviceCode":Device.IDFA])
        session.request("\(apiHost)/api/login/deviceCode",
                        method: .post,
                        parameters: ["deviceCode":Device.IDFA,
                                     "sign":sign])
        .responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any],
                      let current = jsonDic["code"] as? String, current == "200", let result = jsonDic["result"] as? [String :Any], let model = AccountModel.deserialize(from: result) else { return }
                SqlManager.shared.insert([model])
                Appearance.shared.accoutModel = model
                GlobalRx.loginSuccessSubject.onNext(())
                self.getUserInfo()
                completeClosure?()
            case let .failure(error):
                failureClosure?(error.errorDescription)
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
    func getUserInfo() {
        guard let model = Appearance.shared.accoutModel else { return }
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "userId":"\(model.userId ?? 0)"])
        session.request("\(apiHost)/api/user/infos",
                        method: .get,
                        parameters: ["sign":sign]
        ).responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any], let current = jsonDic["code"] as? String else { return }
                if current == "200", let result = jsonDic["result"] as? [String :Any], let model = userOtherInfo.deserialize(from: result) {
                    if var firstModel = SqlManager.shared.filter(from: AccountModel.self, where: AccountModel.Properties.userId == model.id ?? 0)?.first {
                        firstModel.userOtherInfo = model
                        SqlManager.shared.update(on: [AccountModel.Properties.userOtherInfo], with: firstModel, where: AccountModel.Properties.userId == model.id ?? 0)
                        Appearance.shared.accoutModel = firstModel
                        GlobalRx.userInfoSubject.onNext(firstModel)
                        XLog.d("用户更新成功")
                    }
                }else if current == "8888" {
                    SqlManager.shared.delete(from: AccountModel.self)
                    Appearance.shared.accoutModel = nil
                    XLog.d("用户退出成功")
                }
            case let .failure(error):
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
    func appleLogin(_ identity: String, completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
        let time = getTimestamp()
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "timestamp":time])
        session.request("\(apiHost)/api/login/toAppleLogin",
                        method: .post,
                        parameters: ["sign":sign,
                                     "identity":identity,
                                     "timestamp":time])
        .responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any],
                      let current = jsonDic["code"] as? String, current == "200", let result = jsonDic["result"] as? [String :Any], let model = AccountModel.deserialize(from: result) else { return }
                SqlManager.shared.insert([model])
                Appearance.shared.accoutModel = model
                GlobalRx.loginSuccessSubject.onNext(())
                self.getUserInfo()
                completeClosure?()
            case let .failure(error):
                failureClosure?(error.errorDescription)
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
//    func googleLogin(_ identity: String, completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
//        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
//                                                               "token":identity])
//        session.request("\(apiHost)/api/login/google",
//                        method: .post,
//                        parameters: ["sign":sign,
//                                     "token":identity])
//        .responseData { resp in
//            self.statRequest(resp)
//            switch resp.result{
//            case let .success(data):
//                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
//                guard let jsonDic = JSON as? [String: Any],
//                      let current = jsonDic["code"] as? String, current == "200", let result = jsonDic["result"] as? [String :Any] else { return }
//                self.accountData(result: result)
//                completeClosure?()
//            case let .failure(error):
//                failureClosure?(error.errorDescription)
//                XLog.d("getActivityMsg", "sync fail", error)
//            }
//        }
//    }
    
//    func faceBookLogin(_ fbInfo: [String: Any], completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
//        let sign = RequestService.instance.generateHash(data: ["systemId":system_id])
//        session.request("\(apiHost)/api/login/facebook",
//                        method: .post,
//                        parameters: ["sign":sign,
//                                     "fbInfo":fbInfo], encoding: JSONEncoding.default)
//        .responseJSON { resp in
//            switch resp.result {
//            case .success(let value):
//                if let jsonDic = value as? [String: Any],
//                   let current = jsonDic["code"] as? String, current == "200",
//                   let result = jsonDic["result"] as? [String :Any] {
//                    self.accountData(result: result)
//                    completeClosure?()
//                }
//            case .failure(let error):
//                failureClosure?(error.errorDescription)
//                XLog.d("getActivityMsg", "sync fail", error)
//            }
//        }
//    }
    

//    
    func editUserInfo(icon:String, nickName:String, completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "userId":"\(Appearance.shared.accoutModel?.userId ?? 0)"])
        session.request("\(apiHost)/api/user/edit",
                        method: .post,
                        parameters: ["sign":sign,
                                     "img_url":icon,
                                     "nickname":nickName]
        ).responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any],
                      let current = jsonDic["code"] as? String, current == "200" else { 
                    failureClosure?("")
                    return
                }
                completeClosure?()
            case let .failure(error):
                failureClosure?(error.errorDescription)
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
    
    func feedback(mobile:String, content:String, completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "mobile":mobile])
        session.request("\(apiHost)/api/user/feedback",
                        method: .post,
                        parameters: ["sign":sign,
                                     "mobile":mobile,
                                     "content":content]
        ).responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any],
                      let current = jsonDic["code"] as? String, current == "200" else { return }
                completeClosure?()
            case let .failure(error):
                failureClosure?(error.errorDescription)
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
    func deleteUser(completeClosure: (() -> Void)?, failureClosure: ((String?) -> Void)?) {
        let time = getTimestamp()
        let sign = RequestService.instance.generateHash(data: ["systemId":system_id,
                                                               "timestamp":time])
        session.request("\(apiHost)/api/user/logoutUser",
                        method: .post,
                        parameters: ["sign":sign,
                                     "timestamp":time]
        ).responseData { resp in
            self.statRequest(resp)
            switch resp.result{
            case let .success(data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any],
                      let current = jsonDic["code"] as? String, current == "200" else { return }
                completeClosure?()
            case let .failure(error):
                failureClosure?(error.errorDescription)
                XLog.d("getActivityMsg", "sync fail", error)
            }
        }
    }
    
    
    func UploadFile(file: UploadFile, completionHandler: ((String) -> Void)?, failureHandler: ((AFError) -> Void)?) {
        guard let data = file.data else { return }
        let fileName = file.timeName
        let sign = RequestService.instance.generateHash(data: ["userId":"\(Appearance.shared.accoutModel?.userId ?? 0)", "systemId":system_id])
        let params = ["sign": sign]
        session.upload(multipartFormData: { (formData: MultipartFormData) -> () in
            for (key, value) in params {
                formData.append(value.data(using: .utf8)!, withName: key)
            }
            formData.append(data, withName: "file", fileName: fileName, mimeType: file.mime)
        }, to: "\(apiHost)/api/upload/file", method: .post).responseData { response in
            switch response.result {
            case .success(let data):
                let JSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
                guard let jsonDic = JSON as? [String: Any], let code = jsonDic["code"] as? String, code == "200", let result = jsonDic["result"] as? String else { return }
                completionHandler?(result)
            case .failure(let error):
                XLog.d("Error", error)
                failureHandler?(error)
            }
        }
    }
    
    

    
    
    
}


/// 上传文件类
struct UploadFile {
    var id: String              // 内部标示，外部不做使用
    var data: Data?             // 数据流（path/data二选一）
    var path: String?           // 本地绝对路径（path/data二选一）

    var timeName: String {
        let name = (Date().timeIntervalSince1970 * 1000).int.string + String.random(length: 5)
        let ext = self.mimeType?.ext ?? ""
        return name + "." + ext
    }

    private var mimeType: MimeType? {
        guard let data = data else {
            guard let tempPath = path else { return nil }
            let url = URL(fileURLWithPath: tempPath)
            guard let temp = try? Data(contentsOf: url) else { return nil }
            return Swime.mimeType(data: temp)
        }
        return Swime.mimeType(data: data)
    }

    var mime: String {
        mimeType?.mime ?? ""
    }

    /// 构造文件、图片、视频
    init(data: Data?) {
        self.id = Device.IDFA
        self.data = data
    }

    /// 构造文件
    init(path: String?) {
        self.id = Device.IDFA
        self.path = path
    }

}

extension String {
    static func random(length: Int, charset: String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") -> String {
        if length <= 0 {
            return ""
        }
        var result = [Character]()
        let charsetLen = charset.count
        for _ in 0..<length {
            let index = Int.random(in: 0..<charsetLen)
            result.append(charset[charset.index(charset.startIndex, offsetBy: index)])
        }
        return String(result)
    }
}
private let arrayParametersKey = "arrayParametersKey"
 
/// Extenstion that allows an array be sent as a request parameters
extension Array {
    /// Convert the receiver array to a `Parameters` object.
    func asParameters() -> Parameters {
        return [arrayParametersKey: self]
    }
}
